import axios from 'axios';
import { ElNotification, ElMessageBox } from 'element-plus';
import sysConfig from "@/config";
import tool from '@/utils/tool';
import store from '@/store'
import router from '@/router';

axios.defaults.baseURL = ''

axios.defaults.timeout = sysConfig.TIMEOUT

// HTTP request 拦截器
axios.interceptors.request.use(
	(config) => {
		// let token = tool.session.get("TOKEN");
		// if (token) {
		// 	config.headers[sysConfig.TOKEN_NAME] = sysConfig.TOKEN_PREFIX + token
		// }
		if (!sysConfig.REQUEST_CACHE && config.method == 'get') {
			config.params = config.params || {};
			config.params['_'] = new Date().getTime();
		}
		Object.assign(config.headers, sysConfig.HEADERS)
		return config;
	},
	(error) => {
		return Promise.reject(error);
	}
);

//FIX 多个API同时401时疯狂弹窗BUG
let MessageBox_401_show = false

// HTTP response 拦截器
axios.interceptors.response.use(
	(response) => {
		return response;
	},
	(error) => {
		if (error.response) {
			if (error.response.status == 404) {
				ElNotification.error({
					title: '请求错误',
					message: "Status:404，正在请求不存在的服务器记录！"
				});
			} else if (error.response.status == 500) {
				ElNotification.error({
					title: '请求错误',
					message: error.response.data.message || "Status:500，服务器发生错误！"
				});
			} else if (error.response.status == 401) {
				if (!MessageBox_401_show) {
					MessageBox_401_show = true
					ElMessageBox.confirm('当前用户已被登出或无权限访问当前资源，请尝试重新登录后再操作。', '无权限访问', {
						type: 'error',
						closeOnClickModal: false,
						center: true,
						confirmButtonText: '重新登录',
						beforeClose: (action, instance, done) => {
							MessageBox_401_show = false
							done()
						}
					}).then(() => {
						router.replace({ path: '/login' });
					}).catch(() => {
					})
				}
			} else {
				ElNotification.error({
					title: '请求错误',
					message: error.message || `Status:${error.response.status}，未知错误！`
				});
			}
		} else {
			ElNotification.error({
				title: '请求错误',
				message: "请求服务器无响应！"
			});
		}

		return Promise.reject(error.response);
	}
);

let http = {
	paramsData: {},

	/** post 请求
	 * @param  {string} method 接口
	 * @param  {object} data 请求参数
	 * @param  {object} config 参数
	 */
	post: function (method, data = {}, config = {}) {
		this.formatParams(method, data)
		return new Promise((resolve, reject) => {
			axios({
				method: 'post',
				url: sysConfig.API_URL,
				data: this.paramsData,
				...config
			}).then((response) => {
				if (response.data.code === 0) {
					resolve(response.data)
				} else {
					if (response.data.code === 40002) {
						tool.session.remove("TOKEN")
						tool.data.remove("USER_INFO")
						tool.data.remove("MENU")
						tool.data.remove("PERMISSIONS")
						tool.data.remove("DASHBOARDGRID")
						tool.data.remove("grid")
						store.commit("clearViewTags")
						store.commit("clearKeepLive")
						store.commit("clearIframeList")
					}
					reject(response.data.msg)
				}
			}).catch((error) => {
				reject(error)
			})
		})
	},

	formatParams: function (method, data = {}) {
		let param_json = {};
		let isFormData = false;
		//组装参数
		let params = {
			method: method,
			token: tool.session.get('TOKEN') || '',
			app_key: sysConfig.APP_KEY,
			timeout: sysConfig.TIMEOUT,
			app_version: sysConfig.APP_VER,
			timestamp: Date.now(),
			noncestr: tool.roundStr(),
		}
		if (data instanceof FormData) {
			isFormData = true;
			data.forEach((value, key) => {
				param_json[key] = value
				if (value instanceof File) {
					params[key] = value
				} else {
					param_json[key] = value
				}
			});
		} else {
			for (let key in data) {
				let value = data[key]
				if (typeof value === 'function') continue;
				param_json[key] = value
			}
		}
		params.param_json = JSON.stringify(param_json)
		//仅以下参数参与签名
		let sortStr = tool.sortParams({
			method: params.method,
			token: params.token,
			app_key: params.app_key,
			timeout: params.timeout,
			app_version: params.app_version,
			timestamp: params.timestamp,
			noncestr: params.noncestr,
			param_json: params.param_json
		})
		console.log('参数排序', sortStr);
		sortStr = sysConfig.APP_SECRET + sortStr + sysConfig.APP_SECRET
		params.sign = tool.crypto.MD5(sortStr).toUpperCase()
		//判断是否为formdata
		if (!isFormData) {
			this.paramsData = params
		} else {
			const formData = new FormData();
			for (const key in params) {
				formData.append(key, params[key]);
			}
			this.paramsData = formData
		}
	}
}

export default http;
